package us.icitap.cm.ui.policecase;

import java.util.List;

import us.icitap.cm.CaseManagementUI;
import us.icitap.cm.business.entities.PenalCode;
import us.icitap.cm.business.entities.PoliceCode;
import us.icitap.cm.ui.custom.CustBeanFieldGroup;
import us.icitap.cm.ui.custom.CustButton;
import us.icitap.cm.ui.custom.CustComboBox;
import us.icitap.cm.ui.custom.CustListSelect;
import us.icitap.cm.ui.custom.CustTextArea;
import us.icitap.cm.ui.custom.CustTextField;
import us.icitap.cm.ui.custom.CustomFormLayout;
import us.icitap.cm.ui.shared.GeneralVars;
import us.icitap.cm.ui.shared.PoliceCodeContainer;
import us.icitap.cm.utils.HandleNotification;
import us.icitap.utils.Result;

import com.vaadin.data.Item;
import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.event.Action;
import com.vaadin.event.Action.Handler;
import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
import com.vaadin.ui.AbstractSelect.NewItemHandler;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomField;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Label;
import com.vaadin.ui.Tree;
import com.vaadin.ui.Tree.ItemStyleGenerator;
import com.vaadin.ui.VerticalLayout;

public class PoliceCodeLayout extends VerticalLayout {
	 private static final Action ACTIVE = new Action("Aktive");
	 private static final Action NON_ACTIVE = new Action("Jo-Aktive");
	
	 private PoliceCode policeCode;
	 private final HorizontalSplitPanel hsl = new HorizontalSplitPanel();
	 
	 private final Tree policeCodeTree = new Tree("Kodi policor");
	 HierarchicalContainer hContainer = new PoliceCodeContainer();
	 
	 final CustomFormLayout cfl = new CustomFormLayout("500px", "Kodi policor", "Pastro", "Ruaj");
	 final VerticalLayout contentLayout = new VerticalLayout();
	 
	 boolean editableVisible = false;
	 boolean readOnlyVisible = false;
	 
	 private CustTextField kodiPrindField = new CustTextField("Kodi prind");
	 private CustTextField policeCodeField = new CustTextField("Kodi");
	 private CustTextArea policeCodeTagField = new CustTextArea("Emertimi");
	 
	 private final CustBeanFieldGroup<PoliceCode> binder = new CustBeanFieldGroup<PoliceCode>(PoliceCode.class);
	 private PenalCodeField penalCodeField;
	 
	 public PoliceCodeLayout(){
		 addComponentAsFirst(hsl);
		 
		 VerticalLayout vlfirst = new VerticalLayout();
		 vlfirst.addComponent(this.policeCodeTree);
		 hsl.setFirstComponent(vlfirst);
		 
		 contentLayout.setMargin(true);
		 hsl.setSecondComponent(contentLayout);
		 hsl.setSplitPosition(30);
		 hsl.setHeight("600");
		
		 policeCodeTree.setContainerDataSource(hContainer);
		 reload();
		 
		 policeCodeTree.setImmediate(true);
		 policeCodeTree.addActionHandler(new Handler(){
			@Override
			public Action[] getActions(Object target, Object sender) {
				if(target instanceof PoliceCode){
					PoliceCode pc = (PoliceCode) target;
					if(pc.isStatus())
						return new Action[]{GeneralVars.ADD, NON_ACTIVE};
					else return new Action[]{ACTIVE};
				}
				return null;
			}

			@Override
			public void handleAction(Action action, Object sender, Object target) {
				// TODO Auto-generated method stub
				if(action == GeneralVars.ADD){
					newChildCode((PoliceCode) target);
					policeCodeTree.select(target);
					policeCodeTree.expandItem(target);
				} else if(action == ACTIVE || action == NON_ACTIVE){
					changeStatus((PoliceCode) target);
					
				}
			}});
		 policeCodeTree.setItemStyleGenerator(new ItemStyleGenerator(){
			@Override
			public String getStyle(Tree source, Object itemId) {
				// TODO Auto-generated method stub
				return null;
			}
			 
		 });

		 penalCodeField = new PenalCodeField(true);
		 
		 FormLayout fl = new FormLayout();
		 kodiPrindField.setWidth("50px");
		 fl.addComponent(kodiPrindField);
		 policeCodeField.setWidth("50px");
		 policeCodeField.setImmediate(true);
		 fl.addComponent(policeCodeField);
		 policeCodeTagField.setImmediate(true);
		 fl.addComponent(policeCodeTagField);
		 fl.addComponent(penalCodeField);
		 cfl.addComponent(fl);
		 cfl.addFooter();
		 cfl.addRightClickListener(new ClickListener(){
			@Override
			public void buttonClick(ClickEvent event) {
				if(policeCodeField.getValue() == null || "".equals(policeCodeField.getValue())){
					HandleNotification.showWarningOnScreen("Kodi nuk mund te jete bosh.");
					policeCodeField.focus();
					return;
				}
				if(policeCodeTagField.getValue() == null){
					HandleNotification.showWarningOnScreen("Emertimi nuk mund te jete bosh.");
					policeCodeTagField.focus();
					return;
				}
				try {
					binder.commit();
					
					boolean newItem = true;
					if(hContainer.containsId(policeCode)){
						newItem = false;
						HandleNotification.showWarningOnScreen("Kodi '"+policeCode.getCode()+"' ndodhet ne liste.");
					}
					if(newItem){
						policeCode.getSuperiorPoliceCode().getChildrenPoliceCode().add(policeCode);
						Result<PoliceCode> result = CaseManagementUI.appStatelessBean.getPersistenceBean().saveEntity(policeCode.getSuperiorPoliceCode());
						if(result.isSucceeded()){
							HandleNotification.showInfoOnTray("Kodi u shtua ne list.");
							reload();
						} else {
							HandleNotification.showWarningOnScreen("Ka ndodhur nje problem gjate ruajtjes.");
							return;
						}
						policeCodeTree.select(policeCode);
						cfl.setRightButtonOkIcon();	
					}
				} catch (CommitException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
			 
		 });
		 
		 binder.bind(kodiPrindField, "superiorPoliceCode.code");
		 binder.bind(policeCodeField, "code");
		 binder.bind(policeCodeTagField, "tag");
		 binder.bind(penalCodeField, "penalCode");
	 }
	 
	 private void reload(){
		 Result<List<PoliceCode>> result = CaseManagementUI.appStatelessBean.getPersistenceBean().getRootPoliceCode();
		 if(result.getObject() != null)
			 ((PoliceCodeContainer)hContainer).reload(result.getObject());
		 		 
		 for(final Object id: policeCodeTree.rootItemIds()){
			 policeCodeTree.expandItemsRecursively(id);
		 }		 
		 policeCodeTree.markAsDirty();
	 }
	 
	 public void showEditableForm(){
//		if (editableVisible)
//			return;

		contentLayout.removeAllComponents();
		cfl.removeRightButtonIcon();
		contentLayout.addComponent(cfl);
		penalCodeField.reload();
		
		editableVisible = true;
		readOnlyVisible = false;
	 }
	 
	 public void showReadOnlyForm(){
		 
	 }
	 
	 private void newChildCode(PoliceCode parent){
		 if(parent == null)
			 throw new NullPointerException();
		 policeCode = new PoliceCode();
		 policeCode.setSuperiorPoliceCode(parent);
		 binder.setItemDataSource(policeCode);
		 showEditableForm();
	 }
	 
	 private boolean changeStatus(PoliceCode code){
		 if(code == null)
			 throw new NullPointerException();
		 code.setStatus(!code.isStatus());
		 if(!code.getChildrenPoliceCode().isEmpty()){
			 for(PoliceCode pc: code.getChildrenPoliceCode())
				 changeStatus(pc);
		 }
		 policeCodeTree.markAsDirty();
		 return true;
	 }

}

class PenalCodeField extends CustomField<PenalCode> {
	private PenalCode penalCode;
	private final CustListSelect penalCodeListSelect = new CustListSelect("Zgjidh nenin");
	private final Label penalCodeTagLabel = new Label("");
	private final CustTextArea newpenalCodeTagField = new CustTextArea("Emertimi");
	private final CustTextField newPenalCodeField = new CustTextField("Neni");
	private final CustButton addNewPenalCodeButton = new CustButton("+");
	private final CustButton saveNewPenalCodeButton = new CustButton("Shto");
//	private List<PenalCode> penalCodeList;
	private final BeanItemContainer<PenalCode> pContainer = new BeanItemContainer<PenalCode>(PenalCode.class);
	
	private final CustBeanFieldGroup<PenalCode> binder = new CustBeanFieldGroup<PenalCode>(PenalCode.class);
	private boolean newData = false;
	private boolean withNewForm = false;
	
	PenalCodeField(boolean withNewForm){
		this.withNewForm = withNewForm;
		Result<List<PenalCode>> result = CaseManagementUI.appStatelessBean.getPersistenceBean().getList(PenalCode.class, true, null);
		if(result.getObject() != null){
//			penalCodeList = result.getObject();
			pContainer.addAll(result.getObject());
		}
	}
	
	PenalCodeField(List<PenalCode> penalCodeList, boolean withNewForm){
		this.withNewForm = withNewForm;
//		this.penalCodeList = penalCodeList;
		pContainer.addAll(penalCodeList);
	}
	
	void reload(){
		Result<List<PenalCode>> result = CaseManagementUI.appStatelessBean.getPersistenceBean().getList(PenalCode.class, true, null);
		if(result.getObject() != null){
//			penalCodeList = result.getObject();
			pContainer.addAll(result.getObject());
		}
		penalCodeListSelect.select(null);
		penalCodeTagLabel.setValue("");
		showPenalForm(false);
	}

	@Override
	protected Component initContent() {
		penalCodeListSelect.setContainerDataSource(pContainer);
		penalCodeListSelect.setImmediate(true);
		penalCodeListSelect.setItemCaptionMode(ItemCaptionMode.PROPERTY);
		penalCodeListSelect.setItemCaptionPropertyId("clauseCode");
		penalCodeListSelect.setWidth("80px");
		penalCodeListSelect.setRows(8);
		penalCodeListSelect.setNullSelectionAllowed(false);
		
		HorizontalLayout listHl = new HorizontalLayout();
		listHl.setSizeFull();
		listHl.addComponent(penalCodeListSelect);
		listHl.addComponent(penalCodeTagLabel);
		penalCodeTagLabel.setHeight("150px");
		
		newPenalCodeField.setWidth("80px");
		newPenalCodeField.setImmediate(true);
		newpenalCodeTagField.setImmediate(true);
		
		VerticalLayout vl0 = new VerticalLayout();
		vl0.addComponent(listHl);
		if(withNewForm){
			vl0.addComponent(addNewPenalCodeButton);
			vl0.setComponentAlignment(addNewPenalCodeButton, Alignment.MIDDLE_LEFT);
			vl0.addComponent(newPenalCodeField);
			vl0.addComponent(newpenalCodeTagField);
			vl0.addComponent(saveNewPenalCodeButton);
			vl0.setComponentAlignment(saveNewPenalCodeButton, Alignment.MIDDLE_RIGHT);
			showPenalForm(false);
		}
		CustomFormLayout fl0 = new CustomFormLayout("240px", "Kodi penal");
		fl0.addComponent(vl0);
		
		VerticalLayout vl = new VerticalLayout();
		vl.addComponent(fl0);
		
		addNewPenalCodeButton.addClickListener(new ClickListener(){
			@Override
			public void buttonClick(ClickEvent event) {
				penalCode = new PenalCode();
				penalCode.setStatus(true);
				binder.setItemDataSource(penalCode);
				
				showPenalForm(true);
				
			}
			
		});
		
		saveNewPenalCodeButton.addClickListener(new ClickListener(){
			@Override
			public void buttonClick(ClickEvent event) {
				if(newPenalCodeField.getValue() == null || "".equals(newPenalCodeField.getValue())){
					HandleNotification.showWarningOnScreen("Neni nuk duhet te jete bosh.");
					return;
				}
				if(newpenalCodeTagField.getValue() == null){
					HandleNotification.showWarningOnScreen("Emertimi nuk duhet te jete bosh.");
					return;
				}
				try {
					binder.commit();
					if(pContainer.addBean(penalCode) == null){
						HandleNotification.showWarningOnScreen("Neni '"+penalCode.getClauseCode()+"' ndodhet ne liste.");
						newPenalCodeField.focus();
						return;
					}
					penalCodeListSelect.select(penalCode);
				} catch (CommitException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				HandleNotification.showInfoOnTray("Neni u shtua ne liste.");
				showPenalForm(false);
			}
			
		});
		
		penalCodeListSelect.addValueChangeListener(new ValueChangeListener(){
			@Override
			public void valueChange(
					com.vaadin.data.Property.ValueChangeEvent event) {
				if(penalCodeListSelect.getValue() != null){
					penalCode = (PenalCode) penalCodeListSelect.getValue();
					penalCodeTagLabel.setValue(""+penalCode.getClauseTag());
				}
			}
		});
		
		binder.bind(newPenalCodeField, "clauseCode");
		binder.bind(newpenalCodeTagField, "clauseTag");
		
		
		return vl;
	}
	
	private void showPenalForm(boolean newData){
		addNewPenalCodeButton.setVisible(!newData);
		newPenalCodeField.setVisible(newData);
		newpenalCodeTagField.setVisible(newData);
		saveNewPenalCodeButton.setVisible(newData);
		this.newData = newData;
	}


	@Override
	public Class<? extends PenalCode> getType() {
		return PenalCode.class;
	}
	
	@Override
	protected void setInternalValue(PenalCode newValue){
		super.setInternalValue(newValue);
		penalCode = newValue;
	}
	
	@Override
	protected PenalCode getInternalValue(){
		penalCode = (PenalCode) penalCodeListSelect.getValue();
		return penalCode;
	}

}
